﻿using IdentityModel;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using OpenIddict.Abstractions;
using OpenIddict.Server.AspNetCore;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Security.Claims;
using System.Threading.Tasks;
using Volo.Abp.Identity;
using Volo.Abp.OpenIddict.ExtensionGrantTypes;
using Wuther.Infrastructure.WeChat;
using static OpenIddict.Abstractions.OpenIddictConstants;

namespace Wuther.Infrastructure.ExtensionGrantTypes
{
    public class WeChatGrantType: ITokenExtensionGrant
    {

        public string Name => ExtensionGrantType.WeChat;

        public async Task<IActionResult> HandleAsync(ExtensionGrantContext context)
        {
            var code = context.Request.GetParameter("code").Value.ToString();
            if (string.IsNullOrEmpty(code))
            {
                return new ForbidResult(
                    new[] { OpenIddictServerAspNetCoreDefaults.AuthenticationScheme },
                    properties: new AuthenticationProperties(new Dictionary<string, string>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidRequest
                    }!));
            }
            //调用wechat api 获取登录结果、openid和unionid
            var wechatAppService = context.HttpContext.RequestServices.GetRequiredService<IWechatAppService>();
            //var wechatSession = await wechatAppService.GetWeChatSessionAsync(code);
            var wechatSession = new LoginResult()
            {
                errcode = 0,
                openid = "aashaca213",
                unionid = "12211",
                session_key = "wechat"
            };
            switch (wechatSession.errcode)
            {
                case 0:
                    string providerKey = wechatSession.openid;
                    ExtensionValidate validate = new ExtensionValidate(); 
                    return await validate.ServerValidate(context, Name, providerKey);
                default:
                    return new ForbidResult(
                    new[] { OpenIddictServerAspNetCoreDefaults.AuthenticationScheme },
                    properties: new AuthenticationProperties(new Dictionary<string, string>
                    {
                        [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidRequest,
                        ["errmsg"] = wechatSession.errmsg
                    }!));
            }
        }

        //private async Task<IActionResult> ServerValidate(ExtensionGrantContext context, string loginProvider, string providerKey)
        //{
        //    var userManager = context.HttpContext.RequestServices.GetRequiredService<IdentityUserManager>();
        //    var user = await userManager.FindByLoginAsync(loginProvider, providerKey);
        //    if (user == null)
        //    {
        //        await RegisterLogin(context, providerKey);
        //        user = await userManager.FindByLoginAsync(loginProvider, providerKey);
        //    }

        //    // Create the claims-based identity that will be used by OpenIddict to generate tokens.
        //    var identity = new ClaimsIdentity(
        //        authenticationType: TokenValidationParameters.DefaultAuthenticationType,
        //        nameType: Claims.Name,
        //        roleType: Claims.Role);

        //    // Add the claims that will be persisted in the tokens.
        //    identity.AddClaim(Claims.Subject, await userManager.GetUserIdAsync(user))
        //            .AddClaim(Claims.Email, await userManager.GetEmailAsync(user))
        //            .AddClaim(Claims.Name, await userManager.GetUserNameAsync(user));

        //    var roles = await userManager.GetRolesAsync(user);
        //    foreach (var role in roles)
        //    {
        //        identity.AddClaim(Claims.Role, role.ToString());
        //    }

        //    long authTime = (long)(DateTime.Now.ToLocalTime() - DateTime1970).TotalSeconds;
        //    identity.AddClaim(Claims.AuthenticationTime, authTime.ToString());

        //    foreach (Claim claim in identity.Claims)
        //    {
        //        claim.SetDestinations(GetDestinations(claim));
        //    }

        //    var principal = new ClaimsPrincipal(identity);
        //    // Note: in this sample, the granted scopes match the requested scope
        //    // but you may want to allow the user to uncheck specific scopes.
        //    // For that, simply restrict the list of scopes before calling SetScopes.
        //    var scopeStr = context.Request.GetParameter("scope").Value.ToString();
        //    if (!string.IsNullOrEmpty(scopeStr))
        //    {
        //        var scopes = scopeStr.Split(',').ToImmutableArray();
        //        principal.SetScopes(scopes);
        //        principal.SetResources(await GetResourcesAsync(context, scopes));
        //    }


        //    //var userClaimsPrincipalFactory = context.HttpContext.RequestServices.GetRequiredService<IUserClaimsPrincipalFactory<IdentityUser>>();
        //    //var claimsPrincipal = await userClaimsPrincipalFactory.CreateAsync(user);
        //    //claimsPrincipal.SetScopes(principal.GetScopes());
        //    //claimsPrincipal.SetResources(await GetResourcesAsync(context, principal.GetScopes()));
        //    //await context.HttpContext.RequestServices.GetRequiredService<AbpOpenIddictClaimDestinationsManager>().SetAsync(principal);
        //    return new SignInResult(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, principal);
        //    //return new GrantValidationResult(principal);
        //}

        //private async Task RegisterLogin(ExtensionGrantContext context, string phoneNumber)
        //{
        //    var userManager = context.HttpContext.RequestServices.GetRequiredService<IdentityUserManager>();

        //    var user = (await userManager.GetUsersForClaimAsync(new Claim(JwtClaimTypes.PhoneNumber, phoneNumber))).FirstOrDefault();
        //    if (user == null)
        //    {
        //        //var userName = GetRandomString(8);
        //        user = new IdentityUser(Guid.NewGuid(), phoneNumber, $"{phoneNumber}@ilawyer.com", null);
        //        user.SetPhoneNumber(phoneNumber, true);
        //        var result = userManager.CreateAsync(user, "Pass123$").Result;
        //        if (!result.Succeeded)
        //        {
        //            throw new Exception(result.Errors.First().Description);
        //        }
        //        //添加短信登录角色
        //        await userManager.AddToRoleAsync(user, "sms");
        //        //result = userManager.AddClaimsAsync(user, new Claim[]{
        //        //    new Claim(JwtClaimTypes.Name,user.Name),
        //        //    new Claim(JwtClaimTypes.PhoneNumber, phoneNumber),
        //        //    new Claim(JwtClaimTypes.GivenName, user.UserName),
        //        //    new Claim(JwtClaimTypes.FamilyName, user.NormalizedUserName),
        //        //    new Claim(JwtClaimTypes.Email, user.Email),
        //        //    new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
        //        //    new Claim(JwtClaimTypes.WebSite, "https://valishment.cn"),
        //        //}).Result;
        //        //if (!result.Succeeded)
        //        //{
        //        //    throw new Exception(result.Errors.First().Description);
        //        //}
        //    }
        //    var userLogin = new UserLoginInfo("sms", phoneNumber, "手机号登录");
        //    var loginRes = userManager.AddLoginAsync(user, userLogin).Result;
        //    if (!loginRes.Succeeded)
        //    {
        //        throw new Exception("登陆失败");
        //    }
        //    //var siginResult = _signInManager.ExternalLoginSignInAsync("phone", phoneNumber, isPersistent: false).Result;
        //    //if (!siginResult.Succeeded)
        //    //{
        //    //    throw new Exception("登陆失败");
        //    //}
        //}
    }
}
